﻿using Abp.Application.Services.Dto;
using Abp.Authorization;
using MyCompanyName.AbpZeroTemplate.Authorization;
using MyCompanyName.AbpZeroTemplate.Daybooks.Dto;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyCompanyName.AbpZeroTemplate.Daybooks
{
    using System.Data.Entity;
    using System.Linq.Dynamic;

    using Abp.Linq.Extensions;
    using Abp.Extensions;

    using Abp.AutoMapper;
    using Abp.Domain.Repositories;

    /// <summary>
    /// App Service 尽量薄，使用dto，将ui的输入传入到domain中去，并将领域返回的实体转换为dto输出给ui
    /// </summary>
    [Abp.Authorization.AbpAuthorize(MyCompanyName.AbpZeroTemplate.Authorization.AppPermissions.Pages_Okr_Daybook)]
    public class DaybookAppService : AbpZeroTemplateAppServiceBase, MyCompanyName.AbpZeroTemplate.Daybooks.IDaybookAppService
    {
        /// <summary>
        /// 注入的 领域服务实现类
        ///     业务简单的，直接注入Repository，操作数据库
        /// </summary>
        private readonly DaybookManager _daybookManager;

        public DaybookAppService(DaybookManager daybookManager)
        {
            _daybookManager = daybookManager;
        }

        //[Abp.Domain.Uow.UnitOfWork]
        [AbpAuthorize(AppPermissions.Pages_Okr_Daybook_Create, AppPermissions.Pages_Okr_Daybook_Edit)]// 有一个权限有就能执行这个方法
        public virtual GetDaybookForEditOutput GetDaybookForEdit(NullableIdInput input)
        {
            DaybookEditDto daybookEditDto;
            List<DaybookItemEditDto> daybookItemsEditDto;
            if (input.Id.HasValue) //Editing existing entity ?
            {
                var daybook = _daybookManager.GetById(input.Id.Value);
                daybookEditDto = daybook.MapTo<DaybookEditDto>();

                var items = _daybookManager.GetItemsById(daybook.Id);
                daybookItemsEditDto = items.MapTo<List<DaybookItemEditDto>>();
            }
            else
            {
                var daybook = _daybookManager.FindBy(DateTime.Now.Date, AbpSession.UserId.Value);
                if (daybook != null)
                {
                    daybookEditDto = daybook.MapTo<DaybookEditDto>();
                    var items = _daybookManager.GetItemsById(daybook.Id);
                    daybookItemsEditDto = items.MapTo<List<DaybookItemEditDto>>();
                }
                else
                {
                    daybookEditDto = new DaybookEditDto() { AccountId = AbpSession.UserId.Value, BookDay = DateTime.Now.Date };
                    daybookItemsEditDto = new List<DaybookItemEditDto>();
                }
            }

            for (int i = daybookItemsEditDto.Count; i < 10; i++)
            {
                // 总是补足10个
                daybookItemsEditDto.Add(new DaybookItemEditDto() { State = WorkStatus.NUL });
            }
            return new GetDaybookForEditOutput
            {
                Book = daybookEditDto,
                Items = daybookItemsEditDto.OrderBy(x => x.Index).ToList()
            };
        }


        [AbpAuthorize(AppPermissions.Pages_Okr_Daybook_Create, AppPermissions.Pages_Okr_Daybook_Edit)]// 有一个权限有就能执行这个方法
        public virtual async Task CreateOrUpdateEdition(Dto.CreateOrUpdateDaybookDto input)
        {
            if (!input.Book.Id.HasValue)
            {
                await CreateAsync(input);
            }
            else
            {
                await UpdateAsync(input);
            }
        }


        [Abp.Authorization.AbpAuthorize(MyCompanyName.AbpZeroTemplate.Authorization.AppPermissions.Pages_Okr_Daybook_Create)]
        protected virtual async Task CreateAsync(Dto.CreateOrUpdateDaybookDto input)
        {
            Daybook model = input.Book.MapTo<Daybook>();
            model.Items = input.Items.MapTo<List<DaybookItem>>();
            await _daybookManager.CreateAsync(model);
        }

        [Abp.Authorization.AbpAuthorize(MyCompanyName.AbpZeroTemplate.Authorization.AppPermissions.Pages_Okr_Daybook_Edit)]
        protected virtual async Task UpdateAsync(Dto.CreateOrUpdateDaybookDto input)
        {
            System.Diagnostics.Debug.Assert(input.Book.Id != null && input.Book.Id > 0, "input.Book.Id should be set.");

            Daybook info = await _daybookManager.GetByIdAsync(input.Book.Id.Value);
            info.Remark = input.Book.Remark;
            info.BookDay = input.Book.BookDay;

            var toDels = info.Items.Where(x => !input.Items.Any(f => f.Id == x.Id)).ToList();
            foreach (var delItem in toDels)
            {
                await _daybookManager.DeleteAsync(delItem);
            }

            foreach (var newItem in input.Items)
            {
                var oldItem = info.Items.Where(x => x.Id > 0 && x.Id == newItem.Id).SingleOrDefault();

                if (oldItem != null)
                {
                    oldItem.Customer = newItem.Customer;
                    oldItem.ManHour = newItem.ManHour.ToString();
                    oldItem.No = newItem.Index;
                    oldItem.Product = newItem.Product;
                    oldItem.Remark = newItem.Remark;
                    oldItem.State = newItem.State;
                    oldItem.Work = newItem.Work;
                }
                else
                {
                    var newitem = newItem.MapTo<DaybookItem>();
                    info.Items.Add(newitem);
                }
            }
            await _daybookManager.UpdateAsync(info);
        }



        public virtual PagedResultOutput<DaybookListDto> GetDaybooks(GetDaybooksInput input)
        {
            var query = _daybookManager.Daybooks
                //.Include(u => u)
                .WhereIf(
                    input.AccountId.HasValue,
                    x =>
                        x.AccountId == input.AccountId.Value)
                .WhereIf(
                    input.StartDate.HasValue,
                    x =>
                        x.BookDay >= input.StartDate)
                .WhereIf(
                    input.EndDate.HasValue,
                    x =>
                        x.BookDay <= input.EndDate)

                //.WhereIf(
                //    !input.Filter.IsNullOrWhiteSpace(),
                //    u =>
                //        u.Customer.Contains(input.Filter) ||
                //        u.Product.Contains(input.Filter) ||
                //        u.Work.Contains(input.Filter) ||
                //        u.Remark.Contains(input.Filter) ||
                //        u.AccountName.Contains(input.Filter)
                //)
                ;

            var resCount = query.Count();
            var dbLst = query
                .OrderBy(input.Sorting)
                .PageBy(input)
                .ToList();

            var resListDtos = dbLst.MapTo<List<DaybookListDto>>();

            return new PagedResultOutput<DaybookListDto>(
                resCount,
                resListDtos
                );
        }



    }
}
